﻿Public Module Projection_V2

    ''' <summary>
    ''' Capital restant dû en fin de période NumPeriode
    ''' </summary>
    ''' <param name="NumPeriode">Numéro de la période d'observation</param>
    ''' <param name="DureePret">Durée du prêt en nombre de période</param>
    ''' <param name="CI">Capital initial</param>
    ''' <param name="TxNomPer">Taux nominal de la période</param>
    ''' <param name="Vision"></param>
    ''' <param name="Terme"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CRD(ByVal NumPeriode As Integer, _
                        ByVal DureePret As Integer, _
                        ByVal CI As Double, _
                        ByVal TxNomPer As Double, _
                        ByVal Vision As TypeVision, _
                        ByVal Terme As TypeTerme) As Double

        Dim result As Double
        If Terme = TypeTerme.AVANCE Then NumPeriode = NumPeriode - 1
        If Terme = TypeTerme.TERME Then
            result = CI * ((1 + TxNomPer) ^ DureePret - (1 + TxNomPer) ^ NumPeriode) / ((1 + TxNomPer) ^ DureePret - 1)
        Else
            result = CI * (1 + TxNomPer) ^ (NumPeriode - 1) - (CI * ((1 + TxNomPer) ^ (DureePret - 1) / (1 - (1 + TxNomPer) ^ DureePret))) * (1 - (1 + TxNomPer) ^ NumPeriode)
        End If

        Return result
    End Function

    ''' <summary>
    ''' Calcul l'âge d'un individu au milieu du NumMois ème mois après la souscription
    ''' </summary>
    ''' <param name="NumMois">Numéro du mois après la souscription</param>
    ''' <param name="ageInit">Age à la soouscription</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function AgeMilieuMois(ByVal NumMois As Integer, ByVal ageInit As Double) As Double
        Return ageInit + (NumMois / 12 - 1 / 24)
    End Function

    ''' <summary>
    ''' Calcul du taux de mortalité d'un individu d'âge exacte 'Age' à partir de la table 'TxMortAn'
    ''' Un taux d'abattement annuel
    ''' </summary>
    ''' <param name="age">Age exacte</param>
    ''' <param name="txMortAn">Taux de mortalité annuels</param>
    ''' <param name="sel_medicale">Taux d'abattement annuels sur la mortalité liés à la sélection médicale</param>
    ''' <param name="NumPeriode">Numéro de la période de projection</param>
    ''' <param name="presence_sel_medic">Prise en compte de la sélection médicale</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function MortaliteMilieuMois(ByVal Age As Double, _
                                        ByVal txMortAn As Double(,), _
                                        ByVal sel_medicale As Double(), _
                                        ByVal NumPeriode As Integer, _
                                        ByVal presence_sel_medic As Boolean) As Double

        Dim coefBorneMin As Double = 1 - (Age - Int(Age))
        Dim coefBorneMax As Double = 1 - coefBorneMin
        Dim TxMortAge As Double = coefBorneMin * txMortAn(Age, 1) + coefBorneMax * txMortAn(Age + 1, 1)
        Dim Abt_SelMed As Double

        If presence_sel_medic Then

            Dim coef_borneMinSelMed As Double = 1 - (NumPeriode / 12 - (Int(NumPeriode / 12)))
            Dim coef_borneMaxSelMed As Double = 1 - coef_borneMinSelMed
            Dim selMed_borneMin, selMed_borneMax

            If Int(NumPeriode / 12) > sel_medicale.Count - 1 Then
                selMed_borneMin = 0
            Else
                selMed_borneMin = sel_medicale(Int(NumPeriode / 12))
            End If

            If Int(NumPeriode / 12) + 1 > sel_medicale.Count - 1 Then
                selMed_borneMax = 0
            Else
                selMed_borneMax = sel_medicale(Int(NumPeriode / 12) + 1)
            End If

            Abt_SelMed = coef_borneMinSelMed * selMed_borneMin + coef_borneMaxSelMed * selMed_borneMax

        End If

        Return TxMortAge * (1 - Abt_SelMed)
    End Function

    ''' <summary>
    ''' Nombre de cotisants en fin de période NumPer
    ''' </summary>
    ''' <param name="NumPer">Numéro de la période d'observation</param>
    ''' <param name="nbEmprInit">Nombre initial d'emprunteurs</param>
    ''' <param name="Cotisants_PrecPer">Nombre de cotisants de la précédentes période d'observation</param>
    ''' <param name="txRemb">Taux de remboursement anticipé sur la période</param>
    ''' <param name="tx_mortaliteMilPer">Taux de mortalité de la période</param>
    ''' <returns>Nombre de cotisants en fin de période NumPer</returns>
    ''' <remarks></remarks>
    Public Function Cotisants(ByVal NumPer As Integer, _
                              ByVal nbEmprInit As Double, _
                              ByVal Cotisants_PrecPer As Double, _
                              ByVal txRemb As Double, _
                              ByVal tx_mortaliteMilPer As Double) As Double

        Return (1 - tx_mortaliteMilPer) * Cotisants_PrecPer * (1 - txRemb)

    End Function


    'Public Function Nb_INCINV(ByVal NumPer As Integer, _
    '                          ByVal nbInitEmpr As Double, _
    '                          ByVal tx_entree_INCINV As Double, _
    '                          ByVal ages As Double, _
    '                          ByVal cotisants As Double, _
    '                          ByVal tableMaintienINCINV As ITableMaintienINCAPINVAL) As Object

    '    'nb_ind_INC_INV contient les nombres d'individus en incap/inval (avec un franchise égale à 0 jours) par survenance et fin d'année d'observation
    '    'nb_inc_inv_evol contient l'évolution des nombres de valides et sinistrés (après franchise) par année d'observation
    '    Dim nb_ind_INC_INV(nbPer - 1, nbPer - 1) As Double
    '    Dim nb_incinv_evol(nbPer - 1, 3) As Double
    '    Dim result(1) As Object

    '    nb_incinv_evol(0, 0) = nbInitEmpr

    '    Dim ageSurv As Double, nbMoisMaintien As Integer, tx_maintien As Double

    '    'Période d'observation

    '    'Pour toutes les survenances i antérieures à la période d'observation
    '    For i = 1 To NumPer - 1
    '        'L'âge à la survenance i est le suivant (le 1er indice du tableau des âges =0 ce qui explique le -1) :
    '        ageSurv = ages(i - 1)
    '        'Le nombre de mois de maintien en sinistre à la date d'observation est le suivant
    '        'Le +1 vient du fait que l'on suppose que les entrées interviennent en début de mois
    '        nbMoisMaintien = n - i + 1
    '        'La proba de maintien en incap inval en n pour une entrée à la survenance i s'écrit donc :
    '        tx_maintien = tableMaintienINCINV.Proba_Maintien(nbMoisMaintien, ageSurv)
    '        'On en déduit le nombre d'individus en incap/inval en n dont le sinistre est survenu en i
    '        nb_ind_INC_INV(i - 1, n - 1) = nb_incinv_evol(i - 1, 0) * tx_entree_INCINV * tx_maintien
    '    Next i

    '    nb_ind_INC_INV(n - 1, n - 1) = nb_incinv_evol(n - 1, 0) * tx_entree_INCINV * tableMaintienINCINV.Proba_Maintien(1, ages(n - 1))

    '    'Le nombre de valides en fin de période est égal au nombre de cotisants fin de période
    '    '- nb sinistrés après période de franchise
    '    Dim nb_sin_incinv As Integer = 0

    '    'Ici, on calcule le nombre d'individus en INCAP/INVAL en fin de période n
    '    For i = 1 To n - 3
    '        'Le nombre d'individus en INCAP/INVAL en fin de période n est égal à la somme de tous
    '        'les individus entrés en INCAP/INVAL avant n et qui ont dépassé la franchise
    '        nb_incinv_evol(n - 1, 3) = nb_incinv_evol(n - 1, 3) + nb_ind_INC_INV(i - 1, n - 1)
    '    Next i

    '    'Ici on calcul le nombre d'individus valides en fin de période n
    '    nb_incinv_evol(n - 1, 1) = cotisants(n - 1, 1) - nb_incinv_evol(n - 1, 3)

    '    'Ici on initialise les nombres d'individus valides (colonne 0)
    '    'et les nombres d'individus en sinistre (colonne 2) en début de période n+1 (indice n dans le tableau)
    '    If n < nbPer Then
    '        nb_incinv_evol(n, 0) = nb_incinv_evol(n - 1, 1)
    '        nb_incinv_evol(n, 2) = nb_incinv_evol(n - 1, 3)
    '    End If

    '    result(0) = nb_incinv_evol
    '    result(1) = nb_ind_INC_INV

    '    Nb_INCINV = result

    'End Function

End Module
